using DocumentCreationSystem.Models;
using Microsoft.Extensions.Logging;
using System.Text.Json;
using System.Collections.Concurrent;

namespace DocumentCreationSystem.Services
{
    /// <summary>
    /// 协作服务 - 支持多用户协作编辑、版本控制、冲突解决
    /// </summary>
    public interface ICollaborationService
    {
        Task<CollaborationSession> CreateSessionAsync(string projectId, string userId, CollaborationMode mode);
        Task<bool> JoinSessionAsync(string sessionId, string userId, UserRole role);
        Task<bool> LeaveSessionAsync(string sessionId, string userId);
        Task<List<CollaborationChange>> GetChangesAsync(string sessionId, DateTime since);
        Task<bool> ApplyChangeAsync(string sessionId, CollaborationChange change);
        Task<ConflictResolutionResult> ResolveConflictAsync(string sessionId, ConflictResolutionRequest request);
        Task<List<ActiveUser>> GetActiveUsersAsync(string sessionId);
        Task<bool> LockResourceAsync(string sessionId, string resourceId, string userId, TimeSpan duration);
        Task<bool> UnlockResourceAsync(string sessionId, string resourceId, string userId);
        Task<SyncResult> SyncChangesAsync(string sessionId, List<CollaborationChange> changes);
    }

    public class CollaborationService : ICollaborationService
    {
        private readonly ILogger<CollaborationService> _logger;
        private readonly IVersionControlService _versionControl;
        private readonly IDataStorageService _dataStorage;
        private readonly ConcurrentDictionary<string, CollaborationSession> _activeSessions = new();
        private readonly ConcurrentDictionary<string, ResourceLock> _resourceLocks = new();

        public CollaborationService(
            ILogger<CollaborationService> logger,
            IVersionControlService versionControl,
            IDataStorageService dataStorage)
        {
            _logger = logger;
            _versionControl = versionControl;
            _dataStorage = dataStorage;
        }

        /// <summary>
        /// 创建协作会话
        /// </summary>
        public async Task<CollaborationSession> CreateSessionAsync(string projectId, string userId, CollaborationMode mode)
        {
            try
            {
                var session = new CollaborationSession
                {
                    Id = Guid.NewGuid().ToString(),
                    ProjectId = projectId,
                    CreatedBy = userId,
                    CreatedAt = DateTime.Now,
                    Mode = mode,
                    Status = SessionStatus.Active
                };

                session.Participants.Add(new SessionParticipant
                {
                    UserId = userId,
                    Role = UserRole.Owner,
                    JoinedAt = DateTime.Now,
                    IsActive = true
                });

                _activeSessions[session.Id] = session;

                _logger.LogInformation($"创建协作会话: {session.Id}, 项目: {projectId}, 用户: {userId}");
                return session;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"创建协作会话失败: 项目 {projectId}, 用户 {userId}");
                throw;
            }
        }

        /// <summary>
        /// 加入协作会话
        /// </summary>
        public async Task<bool> JoinSessionAsync(string sessionId, string userId, UserRole role)
        {
            try
            {
                if (!_activeSessions.TryGetValue(sessionId, out var session))
                {
                    _logger.LogWarning($"协作会话不存在: {sessionId}");
                    return false;
                }

                // 检查用户是否已在会话中
                var existingParticipant = session.Participants.FirstOrDefault(p => p.UserId == userId);
                if (existingParticipant != null)
                {
                    existingParticipant.IsActive = true;
                    existingParticipant.LastActiveAt = DateTime.Now;
                }
                else
                {
                    session.Participants.Add(new SessionParticipant
                    {
                        UserId = userId,
                        Role = role,
                        JoinedAt = DateTime.Now,
                        IsActive = true,
                        LastActiveAt = DateTime.Now
                    });
                }

                // 广播用户加入事件
                await BroadcastEventAsync(sessionId, new CollaborationEvent
                {
                    Type = EventType.UserJoined,
                    UserId = userId,
                    Timestamp = DateTime.Now,
                    Data = new { Role = role.ToString() }
                });

                _logger.LogInformation($"用户加入协作会话: {userId} -> {sessionId}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"用户加入协作会话失败: {userId} -> {sessionId}");
                return false;
            }
        }

        /// <summary>
        /// 离开协作会话
        /// </summary>
        public async Task<bool> LeaveSessionAsync(string sessionId, string userId)
        {
            try
            {
                if (!_activeSessions.TryGetValue(sessionId, out var session))
                {
                    return false;
                }

                var participant = session.Participants.FirstOrDefault(p => p.UserId == userId);
                if (participant != null)
                {
                    participant.IsActive = false;
                    participant.LeftAt = DateTime.Now;

                    // 释放用户持有的所有锁
                    await ReleaseUserLocksAsync(sessionId, userId);

                    // 广播用户离开事件
                    await BroadcastEventAsync(sessionId, new CollaborationEvent
                    {
                        Type = EventType.UserLeft,
                        UserId = userId,
                        Timestamp = DateTime.Now
                    });
                }

                _logger.LogInformation($"用户离开协作会话: {userId} <- {sessionId}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"用户离开协作会话失败: {userId} <- {sessionId}");
                return false;
            }
        }

        /// <summary>
        /// 获取变更记录
        /// </summary>
        public async Task<List<CollaborationChange>> GetChangesAsync(string sessionId, DateTime since)
        {
            try
            {
                if (!_activeSessions.TryGetValue(sessionId, out var session))
                {
                    return new List<CollaborationChange>();
                }

                return session.Changes.Where(c => c.Timestamp > since).OrderBy(c => c.Timestamp).ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取变更记录失败: {sessionId}");
                return new List<CollaborationChange>();
            }
        }

        /// <summary>
        /// 应用变更
        /// </summary>
        public async Task<bool> ApplyChangeAsync(string sessionId, CollaborationChange change)
        {
            try
            {
                if (!_activeSessions.TryGetValue(sessionId, out var session))
                {
                    return false;
                }

                // 检查冲突
                var conflicts = await DetectConflictsAsync(sessionId, change);
                if (conflicts.Any())
                {
                    change.Status = ChangeStatus.Conflicted;
                    change.Conflicts = conflicts;
                    
                    // 通知冲突
                    await BroadcastEventAsync(sessionId, new CollaborationEvent
                    {
                        Type = EventType.ConflictDetected,
                        UserId = change.UserId,
                        Timestamp = DateTime.Now,
                        Data = new { ChangeId = change.Id, Conflicts = conflicts }
                    });
                }
                else
                {
                    // 应用变更
                    await ApplyChangeToResourceAsync(change);
                    change.Status = ChangeStatus.Applied;
                    change.AppliedAt = DateTime.Now;

                    // 创建版本快照
                    await _versionControl.CreateSnapshotAsync(change.ResourceId, change.UserId, $"协作变更: {change.Description}");
                }

                session.Changes.Add(change);

                // 广播变更事件
                await BroadcastEventAsync(sessionId, new CollaborationEvent
                {
                    Type = EventType.ChangeApplied,
                    UserId = change.UserId,
                    Timestamp = DateTime.Now,
                    Data = change
                });

                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"应用变更失败: {sessionId}, 变更: {change.Id}");
                return false;
            }
        }

        /// <summary>
        /// 解决冲突
        /// </summary>
        public async Task<ConflictResolutionResult> ResolveConflictAsync(string sessionId, ConflictResolutionRequest request)
        {
            try
            {
                if (!_activeSessions.TryGetValue(sessionId, out var session))
                {
                    return new ConflictResolutionResult { Success = false, Message = "会话不存在" };
                }

                var change = session.Changes.FirstOrDefault(c => c.Id == request.ChangeId);
                if (change == null)
                {
                    return new ConflictResolutionResult { Success = false, Message = "变更不存在" };
                }

                var result = new ConflictResolutionResult();

                switch (request.ResolutionStrategy)
                {
                    case ConflictResolutionStrategy.AcceptCurrent:
                        await ApplyChangeToResourceAsync(change);
                        change.Status = ChangeStatus.Applied;
                        result.Success = true;
                        result.Message = "已接受当前变更";
                        break;

                    case ConflictResolutionStrategy.AcceptIncoming:
                        // 撤销当前变更，应用传入变更
                        await RevertChangeAsync(change);
                        await ApplyChangeToResourceAsync(request.IncomingChange);
                        result.Success = true;
                        result.Message = "已接受传入变更";
                        break;

                    case ConflictResolutionStrategy.Merge:
                        var mergedChange = await MergeChangesAsync(change, request.IncomingChange);
                        await ApplyChangeToResourceAsync(mergedChange);
                        result.Success = true;
                        result.Message = "已合并变更";
                        result.MergedChange = mergedChange;
                        break;

                    case ConflictResolutionStrategy.Manual:
                        if (request.ManualResolution != null)
                        {
                            await ApplyManualResolutionAsync(change, request.ManualResolution);
                            result.Success = true;
                            result.Message = "已应用手动解决方案";
                        }
                        break;
                }

                // 广播冲突解决事件
                await BroadcastEventAsync(sessionId, new CollaborationEvent
                {
                    Type = EventType.ConflictResolved,
                    UserId = request.UserId,
                    Timestamp = DateTime.Now,
                    Data = result
                });

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"解决冲突失败: {sessionId}");
                return new ConflictResolutionResult { Success = false, Message = ex.Message };
            }
        }

        /// <summary>
        /// 获取活跃用户
        /// </summary>
        public async Task<List<ActiveUser>> GetActiveUsersAsync(string sessionId)
        {
            try
            {
                if (!_activeSessions.TryGetValue(sessionId, out var session))
                {
                    return new List<ActiveUser>();
                }

                var activeUsers = session.Participants
                    .Where(p => p.IsActive)
                    .Select(p => new ActiveUser
                    {
                        UserId = p.UserId,
                        Role = p.Role,
                        JoinedAt = p.JoinedAt,
                        LastActiveAt = p.LastActiveAt,
                        CurrentResource = GetUserCurrentResource(sessionId, p.UserId)
                    })
                    .ToList();

                return activeUsers;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取活跃用户失败: {sessionId}");
                return new List<ActiveUser>();
            }
        }

        /// <summary>
        /// 锁定资源
        /// </summary>
        public async Task<bool> LockResourceAsync(string sessionId, string resourceId, string userId, TimeSpan duration)
        {
            try
            {
                var lockKey = $"{sessionId}:{resourceId}";
                var existingLock = _resourceLocks.GetValueOrDefault(lockKey);

                if (existingLock != null && existingLock.ExpiresAt > DateTime.Now && existingLock.UserId != userId)
                {
                    _logger.LogWarning($"资源已被锁定: {resourceId} by {existingLock.UserId}");
                    return false;
                }

                var resourceLock = new ResourceLock
                {
                    SessionId = sessionId,
                    ResourceId = resourceId,
                    UserId = userId,
                    LockedAt = DateTime.Now,
                    ExpiresAt = DateTime.Now.Add(duration)
                };

                _resourceLocks[lockKey] = resourceLock;

                // 广播锁定事件
                await BroadcastEventAsync(sessionId, new CollaborationEvent
                {
                    Type = EventType.ResourceLocked,
                    UserId = userId,
                    Timestamp = DateTime.Now,
                    Data = new { ResourceId = resourceId, Duration = duration }
                });

                _logger.LogInformation($"资源已锁定: {resourceId} by {userId} for {duration}");
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"锁定资源失败: {resourceId}");
                return false;
            }
        }

        /// <summary>
        /// 解锁资源
        /// </summary>
        public async Task<bool> UnlockResourceAsync(string sessionId, string resourceId, string userId)
        {
            try
            {
                var lockKey = $"{sessionId}:{resourceId}";
                if (_resourceLocks.TryGetValue(lockKey, out var existingLock) && existingLock.UserId == userId)
                {
                    _resourceLocks.TryRemove(lockKey, out _);

                    // 广播解锁事件
                    await BroadcastEventAsync(sessionId, new CollaborationEvent
                    {
                        Type = EventType.ResourceUnlocked,
                        UserId = userId,
                        Timestamp = DateTime.Now,
                        Data = new { ResourceId = resourceId }
                    });

                    _logger.LogInformation($"资源已解锁: {resourceId} by {userId}");
                    return true;
                }

                return false;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"解锁资源失败: {resourceId}");
                return false;
            }
        }

        /// <summary>
        /// 同步变更
        /// </summary>
        public async Task<SyncResult> SyncChangesAsync(string sessionId, List<CollaborationChange> changes)
        {
            try
            {
                var result = new SyncResult
                {
                    SessionId = sessionId,
                    SyncedAt = DateTime.Now,
                    TotalChanges = changes.Count
                };

                foreach (var change in changes)
                {
                    var success = await ApplyChangeAsync(sessionId, change);
                    if (success)
                    {
                        result.SuccessfulChanges++;
                    }
                    else
                    {
                        result.FailedChanges++;
                        result.Errors.Add($"变更 {change.Id} 应用失败");
                    }
                }

                _logger.LogInformation($"同步完成: {sessionId}, 成功: {result.SuccessfulChanges}, 失败: {result.FailedChanges}");
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"同步变更失败: {sessionId}");
                throw;
            }
        }

        #region 私有辅助方法

        private async Task<List<ChangeConflict>> DetectConflictsAsync(string sessionId, CollaborationChange change)
        {
            var conflicts = new List<ChangeConflict>();

            if (!_activeSessions.TryGetValue(sessionId, out var session))
            {
                return conflicts;
            }

            // 检查同一资源的并发修改
            var recentChanges = session.Changes
                .Where(c => c.ResourceId == change.ResourceId && 
                           c.Timestamp > change.Timestamp.AddMinutes(-5) &&
                           c.UserId != change.UserId)
                .ToList();

            foreach (var recentChange in recentChanges)
            {
                if (HasOverlap(change, recentChange))
                {
                    conflicts.Add(new ChangeConflict
                    {
                        ConflictingChangeId = recentChange.Id,
                        ConflictType = ConflictType.ConcurrentModification,
                        Description = "同时修改了相同的内容区域"
                    });
                }
            }

            return conflicts;
        }

        private bool HasOverlap(CollaborationChange change1, CollaborationChange change2)
        {
            // 简化的重叠检测逻辑
            if (change1.Position != null && change2.Position != null)
            {
                var pos1 = change1.Position;
                var pos2 = change2.Position;
                
                return !(pos1.End < pos2.Start || pos2.End < pos1.Start);
            }

            return false;
        }

        private async Task ApplyChangeToResourceAsync(CollaborationChange change)
        {
            // 根据变更类型应用到实际资源
            switch (change.Type)
            {
                case ChangeType.TextInsert:
                    await ApplyTextInsertAsync(change);
                    break;
                case ChangeType.TextDelete:
                    await ApplyTextDeleteAsync(change);
                    break;
                case ChangeType.TextReplace:
                    await ApplyTextReplaceAsync(change);
                    break;
                case ChangeType.FormatChange:
                    await ApplyFormatChangeAsync(change);
                    break;
            }
        }

        private async Task ApplyTextInsertAsync(CollaborationChange change)
        {
            // 实现文本插入逻辑
            await Task.Delay(10);
        }

        private async Task ApplyTextDeleteAsync(CollaborationChange change)
        {
            // 实现文本删除逻辑
            await Task.Delay(10);
        }

        private async Task ApplyTextReplaceAsync(CollaborationChange change)
        {
            // 实现文本替换逻辑
            await Task.Delay(10);
        }

        private async Task ApplyFormatChangeAsync(CollaborationChange change)
        {
            // 实现格式变更逻辑
            await Task.Delay(10);
        }

        private async Task RevertChangeAsync(CollaborationChange change)
        {
            // 撤销变更逻辑
            await Task.Delay(10);
        }

        private async Task<CollaborationChange> MergeChangesAsync(CollaborationChange change1, CollaborationChange change2)
        {
            // 合并变更逻辑
            await Task.Delay(10);
            return new CollaborationChange
            {
                Id = Guid.NewGuid().ToString(),
                Type = ChangeType.TextReplace,
                ResourceId = change1.ResourceId,
                UserId = "system",
                Timestamp = DateTime.Now,
                Description = "自动合并变更"
            };
        }

        private async Task ApplyManualResolutionAsync(CollaborationChange change, object manualResolution)
        {
            // 应用手动解决方案
            await Task.Delay(10);
        }

        private async Task BroadcastEventAsync(string sessionId, CollaborationEvent collaborationEvent)
        {
            // 广播事件到所有会话参与者
            // 实际实现可能使用SignalR或其他实时通信技术
            _logger.LogDebug($"广播事件: {collaborationEvent.Type} in session {sessionId}");
            await Task.Delay(1);
        }

        private async Task ReleaseUserLocksAsync(string sessionId, string userId)
        {
            var userLocks = _resourceLocks.Where(kvp => 
                kvp.Value.SessionId == sessionId && kvp.Value.UserId == userId).ToList();

            foreach (var lockPair in userLocks)
            {
                _resourceLocks.TryRemove(lockPair.Key, out _);
            }

            await Task.Delay(1);
        }

        private string? GetUserCurrentResource(string sessionId, string userId)
        {
            // 获取用户当前正在编辑的资源
            var userLocks = _resourceLocks.Where(kvp => 
                kvp.Value.SessionId == sessionId && 
                kvp.Value.UserId == userId && 
                kvp.Value.ExpiresAt > DateTime.Now).ToList();

            return userLocks.FirstOrDefault().Value?.ResourceId;
        }

        #endregion
    }
}
